--记录Luatable的变化
--每次只同步变化量
--只有需要的时候才同步整体量

local metaTable = {
	__index = function(tb, key)
		return tb.tbNewState[key]
	end,
	__newindex = function ( tb, key, value)
		--是否检查数值 或者table相等 相等则不同步
		-- local bc = rawget(tb, "bCheckSame")
		-- if bc then
			-- if tb.tbNewState[key] == value then
			-- 	return
			-- end
		-- end
		
		tb.tbNewState[key] = value
		tb.tbModified[key] = true
	end
}

--不支持数组 不支持字典 这些结构使用RPC自己实现
function Lib:CreateDeltaStateTable( bCheckSame )
	local tb = {}
	tb.tbOldState = {}
	tb.tbNewState = {}
	tb.tbModified = {}
	tb.bCheckSame = bCheckSame
	setmetatable( tb, metaTable )
	return tb
end

function Lib:IsDeltaTable( tb )
	if type(tb) ~= "table" then return false end
	local tbOld = rawget(tb, "tbOldState")
	return tbOld ~= nil
end

--非深层Delta 只有一层Delta状态
function Lib:GetDelta( tb )
	local tbOldState = rawget(tb, "tbOldState")
	local tbNewState = rawget(tb, "tbNewState")
	local tbModified = rawget(tb, "tbModified")
	local tbDelta = {}
	for k, v in pairs(tbModified) do
		tbDelta[k] = tbNewState[k]
		tbOldState[k] = tbNewState[k]
	end

	--清理修改状态
	rawset(tb, "tbModified", {})
	return tbDelta
end

--嵌套DeltaTable获取数据
--[[
DeltaTable = {
	optional int32 nTemplateId = 1;
	optional int32 nBoardId = 2;
 	repeated MapField_NpcSkills NpcSkills = 3;
 }
]]
function Lib:GetDeltaDeep( tb )
	local tbOldState = rawget(tb, "tbOldState")
	local tbNewState = rawget(tb, "tbNewState")
	local tbModified = rawget(tb, "tbModified")
	local tbDelta = {}
	for k, v in pairs(tbModified) do
		if Lib:IsDeltaTable(tbNewState[k]) then
			--发生了变动
			local tn = Lib:GetDeltaDeep(tbNewState[k])			
			if next(tn) then
				tbDelta[k] = tn 
			end
			tbOldState[k] = tbNewState[k]
		else
			tbDelta[k] = tbNewState[k]
			tbOldState[k] = tbNewState[k]
		end
	end

	--清理修改状态
	rawset(tb, "tbModified", {})
	return tbDelta
end

--支持服务器DeltaTable 客户端普通table
function Lib:GetCurState( tb )
	if Lib:IsDeltaTable(tb) then
		local tbNewState = rawget(tb, "tbNewState")
		return tbNewState
	else
		return tb
	end
end

function Lib:ForEachDeltaTB( tb, func)
	local curState = Lib:GetCurState(tb)
	for k, v in pairs(curState) do
		func(k, v)
	end
end
--若Key不存在则创建一个空的DeltaTable
function Lib:GetDeltaTBDeepKey( tb, key)
	local ret = Lib:GetTableDefaultValue(tb, key, AutoChess:MakeDelta())
	-- if Lib:IsDeltaTable(ret) then
	-- 	-- return Lib:GetCurState(ret)
	-- 	--直接返回DeltaTable 上层会正确序列化处理这个DeltaTable 存盘的时候
	-- 	return ret
	-- end
	return ret
end

--玩家数据递归嵌套DeltaTable
function Lib:GetCurStateDeep( tb )
	local fullState = {}
	local tbNewState = rawget(tb, "tbNewState")
	for k, v in pairs(tbNewState) do
		if Lib:IsDeltaTable(v) then
			fullState[k] = Lib:GetCurStateDeep(v)
		else
			fullState[k] = v
		end
	end
	return fullState
end

function Lib:ClearModified( tb )
	self:GetDeltaDeep(tb)
end


--同步带有类型信息用于客户端处理结构
function Lib:SetType( tb, szType)
	tb._Type = szType
end


--浅拷贝
function Lib:CopyDeltaTable( tbA, tbB )
	for k, v in pairs(tbB) do
		tbA[k] = v
	end
end


--深拷贝
--地图同步Delta需要深度拷贝
--如果对象
function Lib:CopyDeltaTableDeep( tbA, tbB )
	for k, v in pairs(tbB) do
		if type(tbA[k]) == "table" and type(v) == "table" then
			self:CopyDeltaTableDeep(tbA[k], v)
		else
			tbA[k] = v
		end
	end
end

--深度拷贝两个Table
function Lib:CopyTBDeep( tbA, tbB)
	for k, v in pairs(tbB) do
		if type(v) == "table" then
			tbA[k]	= Lib:CopyTB(v);
		else
			tbA[k]	= v
		end
	end
end

function Lib:SetDeltaTableKey( tb, key, value )
	if tb[key] == nil then 
		tb[key] = value 
		return
	end

	local tbModified = rawget(tb, "tbModified")
	tbModified[key] = true
	--相同的不需要深度拷贝设置
	if tb[key] == value then return end

	--table 需要深度拷贝
	if type(value) == "table" then
		Lib:CopyDeltaTableDeep(tb[key], value)
	else
		tb[key] = value
	end
end

function Lib:MarkModified( tb, key )
	local tbModified = rawget(tb, "tbModified")
	tbModified[key] = true
end

--将tbB中的成员table 作为新的DetalTable 赋值给A 保证可以递归求Delta
--初始化时候设置
--[[
 optional int32 nTemplateId = 1;
 optional int32 nBoardId = 2;
 repeated MapField_NpcSkills NpcSkills = 3;
]]
function Lib:SafeCopyDeltaTable( tbA, tbB )
	for k, v in pairs(tbB) do
		if type(v) == "table" then
			local db = Lib:CreateDeltaStateTable()
			tbA[k] = db
			Lib:SafeCopyDeltaTable(db, v)
		else
			tbA[k] = v
		end
	end
end

function Lib:SafeSetDelta( tb, key, val )
	if tb[key] == val then return end
	AutoMap.Log("SafeSetDelta", tb, key, val)
	tb[key] = val
end


--浅拷贝 只拷贝第一层的DeltaTable
function Lib:ShadowCopyDeltaTable( tbA, tbB )
	for k, v in pairs(tbB) do
		if type(v) == "table" then
			local db = Lib:CreateDeltaStateTable()
			tbA[k] = db
			Lib:CopyDeltaTable(db, v)
		else
			tbA[k] = v
		end
	end
end

--设置变量的默认值
function Lib:DefaultInitTb( tb, defaultV )
	for k, v in pairs(defaultV) do
		if tb[k] == nil then
			--值类型可以直接赋值 table 类型需要创建一个新的空Table
			if type(v) == "table" then
				tb[k] = {}
			else
				tb[k] = v
			end
		end
	end
end